import logging
import time
from contextlib import asynccontextmanager

import uvicorn
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import ORJSONResponse, RedirectResponse
from langfuse.decorators import langfuse_context

from src.config import settings
from src.globals import (
    create_service_container,
    create_service_metadata,
)
from src.providers import generate_components
from src.utils import (
    init_langfuse,
    setup_custom_logger,
)
from src.utils.llm_health_checker import LLMHealthChecker
from src.web.v1 import routers

setup_custom_logger(
    "wren-ai-service", level_str=settings.logging_level, is_dev=settings.development
)

logger = logging.getLogger("wren-ai-service")


# https://fastapi.tiangolo.com/advanced/events/#lifespan
@asynccontextmanager
async def lifespan(app: FastAPI):
    # startup events
    pipe_components = generate_components(settings.components)
    app.state.service_container = create_service_container(pipe_components, settings)
    app.state.service_metadata = create_service_metadata(pipe_components)
    init_langfuse(settings)

    # 初始化并启动LLM健康检查
    try:
        # 获取SQL生成管道及其生成器
        sql_generation_pipeline = (
            app.state.service_container.ask_service._pipelines.get("sql_generation")
        )
        if sql_generation_pipeline and hasattr(sql_generation_pipeline, "_components"):
            generator = sql_generation_pipeline._components.get("generator")

            if generator:
                # 尝试获取模型名称和API基地址
                model_name = "unknown"
                api_base = "unknown"

                # 创建并启动健康检查器
                app.state.llm_health_checker = LLMHealthChecker(
                    llm_generator=generator,
                    model_name=model_name,
                    api_base=api_base,
                    check_interval=300,  # 每5分钟检查一次
                )
                app.state.llm_health_checker.start_periodic_check()
                logger.info("LLM健康检查器已初始化并启动")
            else:
                logger.error("无法获取LLM生成器")
        else:
            logger.error("无法获取SQL生成管道")
    except Exception as e:
        logger.error(f"初始化LLM健康检查器失败: {str(e)}")

    yield

    # shutdown events
    if hasattr(app.state, "llm_health_checker"):
        app.state.llm_health_checker.stop_periodic_check()
    langfuse_context.flush()


app = FastAPI(
    title="wren-ai-service API Docs",
    lifespan=lifespan,
    redoc_url=None,
    default_response_class=ORJSONResponse,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.include_router(routers.router, prefix="/v1", tags=["v1"])
# TODO: deprecated, it was used for load testing using locust only. should be removed in the future
if settings.development:
    from src.web import development

    app.include_router(development.router, prefix="/dev", tags=["dev"])


@app.exception_handler(Exception)
async def exception_handler(_, exc: Exception):
    return ORJSONResponse(
        status_code=500,
        content={"detail": str(exc)},
    )


@app.exception_handler(RequestValidationError)
async def request_exception_handler(request, exc: Exception):
    logger.error(f"请求验证错误: {str(exc)}")
    # 尝试记录请求体
    try:
        body = await request.json()
        logger.error(f"请求体: {body}")
    except Exception as e:
        logger.error(f"无法解析请求体: {str(e)}")

    return ORJSONResponse(
        status_code=400,
        content={"detail": str(exc)},
    )


@app.get("/")
def root():
    return RedirectResponse(url="/docs")


@app.get("/health")
def health():
    """基本系统健康检查"""
    return {"status": "ok", "service": "wren-ai-service", "timestamp": time.time()}


@app.get("/llm-health")
async def llm_health():
    """测试LLM连接和功能状态"""
    if hasattr(app.state, "llm_health_checker"):
        # 使用健康检查器执行检查
        return await app.state.llm_health_checker.check_health()
    else:
        # 如果健康检查器未初始化，返回错误状态
        return {
            "status": "error",
            "message": "LLM健康检查器未初始化",
            "timestamp": time.time(),
        }


@app.get("/llm-health/status")
def llm_health_status():
    """获取最近一次LLM健康检查结果"""
    if hasattr(app.state, "llm_health_checker"):
        last_result = app.state.llm_health_checker.get_last_check_result()
        if last_result:
            return last_result
        else:
            return {
                "status": "unknown",
                "message": "尚未完成任何健康检查",
                "timestamp": time.time(),
            }
    else:
        return {
            "status": "error",
            "message": "LLM健康检查器未初始化",
            "timestamp": time.time(),
        }


if __name__ == "__main__":
    # 同时监听IPv4和IPv6接口
    # "::" 是所有IPv6接口的意思，等同于IPv6版本的0.0.0.0
    # 大多数uvicorn实现支持通过"::"同时监听IPv4和IPv6
    uvicorn.run(
        "src.__main__:app",
        host="::",  # 同时监听IPv4和IPv6接口
        port=settings.port,
        reload=settings.development,
        reload_includes=["src/**/*.py", ".env.dev", "config.yaml"],
        reload_excludes=["demo/*.py", "tests/**/*.py", "eval/**/*.py"],
        workers=1,
        loop="asyncio",
        http="httptools",
    )
